from turtle import Turtle, Screen, mainloop


class TurtleInteractive(Turtle):
    MOVING, DRAGGING = range(2)  # states

    def __init__(self, screen):
        Turtle.__init__(self)

        self.screen = screen
        self.state = self.MOVING

        # Initially we track the turtle's motion and left button clicks
        self.onmove(self.screen, self.move_handler)  # a la screen.onmove(move_handler)
        self.onclick(self.click_handler)  # a click will turn motion into drag

    def handle_move(self, x, y):
        self.penup()
        self.setheading(self.towards(x, y))
        self.goto(x, y)

    def handle_click(self, x, y):
        pass

    def handle_release(self, x, y):
        pass

    def handle_drag(self, x, y):
        self.pendown()
        self.setheading(self.towards(x, y))
        self.goto(x, y)


    def move_handler(self, x, y):
        if self.state != self.MOVING:  # ignore stray events
            return

        self.onmove(self.screen, None)  # avoid overlapping events
        self.handle_move(x, y)
        self.onmove(self.screen, self.move_handler)

    def click_handler(self, x, y):
        self.onclick(None)  # disable until release
        self.onmove(self.screen, None)  # disable competing handler

        self.onrelease(self.release_handler)  # watch for release event
        self.ondrag(self.drag_handler)  # motion is now dragging until release

        self.handle_click(x, y)

        self.state = self.DRAGGING

    def release_handler(self, x, y):
        self.onrelease(None)  # disable until click
        self.ondrag(None)  # disable competing handler

        self.onclick(self.click_handler)  # watch for click event
        self.onmove(self.screen, self.move_handler)  # dragging is now motion until click

        self.handle_release(x, y)

        self.state = self.MOVING

    def drag_handler(self, x, y):
        if self.state != self.DRAGGING:  # ignore stray events
            return

        self.ondrag(None)  # disable event inside event handler
        self.handle_drag(x, y)
        self.ondrag(self.drag_handler)  # reenable event on event handler exit

    def onmove(self, obj, fun, add=None):
        """
        Bind fun to mouse-motion event on screen.

        Arguments:
        self -- the singular screen instance
        fun  -- a function with two arguments, the coordinates
            of the mouse cursor on the canvas.
        """

        if fun is None:
            obj.cv.unbind('<Motion>')
        else:
            def eventfun(event):
                fun(obj.cv.canvasx(event.x) / obj.xscale, -obj.cv.canvasy(event.y) / obj.yscale)
            obj.cv.bind('<Motion>', eventfun, add)

def draw():
    screen = Screen()
    screen.setup(500, 600)
    screen.screensize(1920, 1080)

    mouse = TurtleInteractive(screen)
    mouse.speed('fastest')

if __name__ == "__main__":
    draw()

    mainloop()
